// utils/api.js - API服务层
// 提供MQTT通信和数据处理的接口

// MQTT 客户端实例
let mqttClient = null
let socketTask = null
let messageHandlers = []
let reconnectTimer = null
let heartbeatTimer = null

/**
 * MQTT API服务
 * 使用 WebSocket 实现 MQTT over WebSocket 连接
 */
const MqttAPI = {
  /**
   * 连接MQTT服务器
   * @param {Object} config - MQTT配置 {host, port, topic}
   * @returns {Promise}
   */
  connect(config) {
    return new Promise((resolve, reject) => {
      console.log('连接MQTT服务器:', config)
      
      // 构建 WebSocket URL
      // 格式: ws://host:port 或 wss://host:port
      const protocol = config.ssl ? 'wss' : 'ws'
      const url = `${protocol}://${config.host}:${config.port}/mqtt`
      
      console.log('WebSocket URL:', url)
      
      // 创建 WebSocket 连接
      socketTask = wx.connectSocket({
        url: url,
        header: {
          'content-type': 'application/json'
        },
        protocols: ['mqtt'], // MQTT 协议
        success: () => {
          console.log('WebSocket 连接请求已发送')
        },
        fail: (err) => {
          console.error('WebSocket 连接失败:', err)
          reject({
            success: false,
            message: '连接失败',
            error: err
          })
        }
      })
      
      // 监听 WebSocket 打开
      socketTask.onOpen((res) => {
        console.log('WebSocket 连接已建立', res)
        mqttClient = socketTask
        
        // 发送 MQTT CONNECT 报文
        this._sendConnectPacket()
        
        // 启动心跳
        this._startHeartbeat()
        
        resolve({
          success: true,
          message: '连接成功'
        })
      })
      
      // 监听 WebSocket 消息
      socketTask.onMessage((res) => {
        console.log('收到服务器消息:', res.data)
        this._handleMessage(res.data)
      })
      
      // 监听 WebSocket 错误
      socketTask.onError((err) => {
        console.error('WebSocket 错误:', err)
        // 尝试重连
        this._reconnect(config)
      })
      
      // 监听 WebSocket 关闭
      socketTask.onClose(() => {
        console.log('WebSocket 连接已关闭')
        mqttClient = null
        this._stopHeartbeat()
        // 尝试重连
        this._reconnect(config)
      })
    })
  },
  
  /**
   * 发送 MQTT CONNECT 报文
   * @private
   */
  _sendConnectPacket() {
    // 简单的 MQTT CONNECT 报文
    // 在实际应用中，应该使用完整的 MQTT 协议格式
    const packet = {
      type: 'connect',
      clientId: 'wx_miniprogram_' + Date.now(),
      keepalive: 60
    }
    
    if (socketTask) {
      socketTask.send({
        data: JSON.stringify(packet),
        success: () => {
          console.log('CONNECT 报文已发送')
        },
        fail: (err) => {
          console.error('发送 CONNECT 报文失败:', err)
        }
      })
    }
  },
  
  /**
   * 启动心跳
   * @private
   */
  _startHeartbeat() {
    this._stopHeartbeat()
    heartbeatTimer = setInterval(() => {
      if (socketTask) {
        socketTask.send({
          data: JSON.stringify({ type: 'ping' }),
          success: () => {
            console.log('心跳已发送')
          }
        })
      }
    }, 30000) // 每 30 秒发送一次心跳
  },
  
  /**
   * 停止心跳
   * @private
   */
  _stopHeartbeat() {
    if (heartbeatTimer) {
      clearInterval(heartbeatTimer)
      heartbeatTimer = null
    }
  },
  
  /**
   * 重连
   * @private
   */
  _reconnect(config) {
    if (reconnectTimer) return
    
    console.log('5秒后尝试重新连接...')
    reconnectTimer = setTimeout(() => {
      reconnectTimer = null
      this.connect(config).catch((err) => {
        console.error('重连失败:', err)
      })
    }, 5000)
  },
  
  /**
   * 处理接收到的消息
   * @private
   */
  _handleMessage(data) {
    try {
      let message = data
      if (typeof data === 'string') {
        message = JSON.parse(data)
      }
      
      console.log('解析后的消息:', message)
      
      // 通知所有监听器
      messageHandlers.forEach(handler => {
        handler(message)
      })
    } catch (e) {
      console.error('解析消息失败:', e)
    }
  },
  
  /**
   * 添加消息监听器
   * @param {Function} handler - 消息处理函数
   */
  onMessage(handler) {
    if (typeof handler === 'function') {
      messageHandlers.push(handler)
    }
  },
  
  /**
   * 移除消息监听器
   * @param {Function} handler - 消息处理函数
   */
  offMessage(handler) {
    const index = messageHandlers.indexOf(handler)
    if (index > -1) {
      messageHandlers.splice(index, 1)
    }
  },

  /**
   * 断开MQTT连接
   * @returns {Promise}
   */
  disconnect() {
    return new Promise((resolve, reject) => {
      console.log('断开MQTT连接')
      
      this._stopHeartbeat()
      
      if (reconnectTimer) {
        clearTimeout(reconnectTimer)
        reconnectTimer = null
      }
      
      if (socketTask) {
        wx.closeSocket({
          success: () => {
            console.log('WebSocket 连接已关闭')
            socketTask = null
            mqttClient = null
            resolve({
              success: true,
              message: '断开连接成功'
            })
          },
          fail: (err) => {
            console.error('关闭 WebSocket 失败:', err)
            reject({
              success: false,
              error: err
            })
          }
        })
      } else {
        resolve({
          success: true,
          message: '连接已断开'
        })
      }
    })
  },

  /**
   * 订阅MQTT主题
   * @param {String} topic - 主题名称
   * @returns {Promise}
   */
  subscribe(topic) {
    return new Promise((resolve, reject) => {
      console.log('订阅主题:', topic)
      
      if (!socketTask) {
        reject({
          success: false,
          message: '未连接到服务器'
        })
        return
      }
      
      const packet = {
        type: 'subscribe',
        topic: topic,
        qos: 0
      }
      
      socketTask.send({
        data: JSON.stringify(packet),
        success: () => {
          console.log('订阅请求已发送')
          resolve({
            success: true,
            message: '订阅成功'
          })
        },
        fail: (err) => {
          console.error('订阅失败:', err)
          reject({
            success: false,
            error: err
          })
        }
      })
    })
  },

  /**
   * 发布消息到MQTT主题
   * @param {String} topic - 主题名称
   * @param {Object} payload - 消息内容
   * @returns {Promise}
   */
  publish(topic, payload) {
    return new Promise((resolve, reject) => {
      console.log('发布消息:', { topic, payload })
      
      if (!socketTask) {
        reject({
          success: false,
          message: '未连接到服务器'
        })
        return
      }
      
      const packet = {
        type: 'publish',
        topic: topic,
        payload: typeof payload === 'string' ? payload : JSON.stringify(payload),
        qos: 0
      }
      
      socketTask.send({
        data: JSON.stringify(packet),
        success: () => {
          console.log('消息已发布')
          resolve({
            success: true,
            message: '发布成功'
          })
        },
        fail: (err) => {
          console.error('发布失败:', err)
          reject({
            success: false,
            error: err
          })
        }
      })
    })
  },

  /**
   * 发送控制命令
   * @param {String} command - 命令类型
   * @param {Object} params - 命令参数
   * @returns {Promise}
   */
  sendCommand(command, params = {}) {
    const payload = {
      command: command,
      device_id: 'pageone_device',
      timestamp: new Date().toISOString(),
      ...params
    }
    
    return this.publish('qtmqtt/topic1', payload)
  },

  /**
   * 发送投喂命令
   * @returns {Promise}
   */
  startFeeding() {
    return this.sendCommand('start_feeding', {
      action: 'start_feeding'
    })
  },

  /**
   * 发送摄像头控制命令
   * @param {Boolean} enable - 开启/关闭
   * @returns {Promise}
   */
  controlCamera(enable) {
    return this.sendCommand('camera_control', {
      action: enable ? 'start' : 'stop'
    })
  },

  /**
   * 请求设备数据
   * @returns {Promise}
   */
  requestDeviceData() {
    return this.sendCommand('request_data', {
      action: 'request_data'
    })
  }
}

/**
 * 数据处理工具
 */
const DataProcessor = {
  /**
   * 解析MQTT消息
   * @param {String} message - 消息内容
   * @returns {Object} 解析后的数据
   */
  parseMessage(message) {
    try {
      const data = JSON.parse(message)
      return {
        success: true,
        data: data
      }
    } catch (e) {
      console.error('解析消息失败:', e)
      return {
        success: false,
        error: '消息格式错误'
      }
    }
  },

  /**
   * 处理温度数据
   * @param {Object} data - 原始数据
   * @returns {Object} 处理后的数据
   */
  processTemperature(data) {
    if (data.temperature === undefined) {
      return null
    }
    
    return {
      value: parseFloat(data.temperature),
      time: new Date().toLocaleString('zh-CN'),
      timestamp: Date.now()
    }
  },

  /**
   * 处理湿度数据
   * @param {Object} data - 原始数据
   * @returns {Object} 处理后的数据
   */
  processHumidity(data) {
    if (data.humidity === undefined) {
      return null
    }
    
    return {
      value: parseFloat(data.humidity),
      time: new Date().toLocaleString('zh-CN'),
      timestamp: Date.now()
    }
  },

  /**
   * 处理食物数据
   * @param {Object} data - 原始数据
   * @returns {Object} 处理后的数据
   */
  processFoodAmount(data) {
    if (data.food_amount === undefined) {
      return null
    }
    
    return {
      value: parseInt(data.food_amount),
      time: new Date().toLocaleString('zh-CN'),
      timestamp: Date.now()
    }
  },

  /**
   * 计算统计数据
   * @param {Array} history - 历史数据数组
   * @returns {Object} 统计结果
   */
  calculateStats(history) {
    if (!history || history.length === 0) {
      return {
        max: 0,
        min: 0,
        avg: 0,
        count: 0
      }
    }
    
    const values = history.map(item => item.value)
    const max = Math.max(...values)
    const min = Math.min(...values)
    const sum = values.reduce((a, b) => a + b, 0)
    const avg = sum / values.length
    
    return {
      max: max,
      min: min,
      avg: avg,
      count: values.length
    }
  }
}

/**
 * 模拟数据生成器
 */
const MockDataGenerator = {
  /**
   * 生成随机温度
   * @param {Number} base - 基准温度
   * @param {Number} range - 波动范围
   * @returns {Number}
   */
  generateTemperature(base = 25, range = 5) {
    return base + (Math.random() - 0.5) * range * 2
  },

  /**
   * 生成随机湿度
   * @param {Number} base - 基准湿度
   * @param {Number} range - 波动范围
   * @returns {Number}
   */
  generateHumidity(base = 50, range = 15) {
    return Math.max(0, Math.min(100, base + (Math.random() - 0.5) * range * 2))
  },

  /**
   * 生成模拟设备数据
   * @returns {Object}
   */
  generateDeviceData() {
    return {
      temperature: this.generateTemperature(),
      humidity: this.generateHumidity(),
      food_amount: Math.floor(Math.random() * 100),
      timestamp: new Date().toISOString()
    }
  },

  /**
   * 生成历史数据
   * @param {Number} count - 数据点数量
   * @param {Number} intervalMinutes - 时间间隔（分钟）
   * @returns {Array}
   */
  generateHistory(count = 30, intervalMinutes = 1) {
    const history = []
    const now = Date.now()
    
    for (let i = count - 1; i >= 0; i--) {
      const time = new Date(now - i * intervalMinutes * 60000)
      history.push({
        time: time.toLocaleTimeString('zh-CN', { 
          hour: '2-digit', 
          minute: '2-digit' 
        }),
        value: this.generateTemperature(),
        timestamp: time.getTime()
      })
    }
    
    return history
  }
}

/**
 * 存储管理器
 */
const StorageManager = {
  /**
   * 保存数据
   * @param {String} key - 键名
   * @param {*} value - 值
   */
  save(key, value) {
    try {
      wx.setStorageSync(key, value)
      return true
    } catch (e) {
      console.error('保存数据失败:', e)
      return false
    }
  },

  /**
   * 读取数据
   * @param {String} key - 键名
   * @param {*} defaultValue - 默认值
   * @returns {*}
   */
  load(key, defaultValue = null) {
    try {
      const value = wx.getStorageSync(key)
      return value !== undefined && value !== '' ? value : defaultValue
    } catch (e) {
      console.error('读取数据失败:', e)
      return defaultValue
    }
  },

  /**
   * 删除数据
   * @param {String} key - 键名
   */
  remove(key) {
    try {
      wx.removeStorageSync(key)
      return true
    } catch (e) {
      console.error('删除数据失败:', e)
      return false
    }
  },

  /**
   * 清空所有数据
   */
  clear() {
    try {
      wx.clearStorageSync()
      return true
    } catch (e) {
      console.error('清空数据失败:', e)
      return false
    }
  }
}

// 导出API
module.exports = {
  MqttAPI,
  DataProcessor,
  MockDataGenerator,
  StorageManager
}

